﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PostSharp.Laos;
using System.Diagnostics;
using System.Data.Objects.DataClasses;
using System.Reflection;

namespace EntityFrameworkContrib.PostSharp4EF
{
    /// <summary>
    /// intercepts calls to collection properties. 
    /// Will use the EDM relationship manager do it's work.
    /// However, during deserialization, normal field storage is used. That is
    /// necessary because we have to be able to initialize the manager ourselves. 
    /// We need both original values and current values at that point without
    /// interference from the manager
    /// </summary>
    [Serializable]
    class OnRelatedCollectionFieldAspect : OnFieldAccessAspect
    {
        string relationshipname, targetrolename;

        public OnRelatedCollectionFieldAspect(string relationshipname, string targetrolename, Type fieldType)
        {
            this.relationshipname = relationshipname;
            this.targetrolename = targetrolename;
        }

        public override void OnGetValue(FieldAccessEventArgs eventArgs)
        {
            if (((ISerializationHelp)eventArgs.Instance).IsDeserializing() == false)
            {
                RelationshipManager manager = ((IEntityWithRelationships)eventArgs.Instance).RelationshipManager;
                IRelatedEnd relatedEnd = manager.GetRelatedEnd(relationshipname, targetrolename);
                eventArgs.ExposedFieldValue = relatedEnd;
            }
            else
            {
                eventArgs.ExposedFieldValue = eventArgs.StoredFieldValue;
            }
        }

        public override void OnSetValue(FieldAccessEventArgs eventArgs)
        {
            /* we would like to get rid of the field because the relationmanager
             * can take care of everything, however, during deserialization
             * there is a moment ('copydatafromsurrogate' call) that we do not yet wish to 
             * use the manager */

            if (((ISerializationHelp)eventArgs.Instance).IsDeserializing())
            {
                eventArgs.StoredFieldValue = eventArgs.ExposedFieldValue;
            }
            else
            {
                throw new NotSupportedException("Can not set relations");
            }


        }


        public override OnFieldAccessAspectOptions GetOptions()
        {
            return OnFieldAccessAspectOptions.None;
        }

    }
}
